<!-- 无缝滚动 -->
 <style lang="scss" scoped>
.infinite-scroll-component-box-left,
.infinite-scroll-component-box-right,
.infinite-scroll-component-box-top,
.infinite-scroll-component-box-bottom {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;

  .scroll-content {
    position: absolute;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;

    &:hover {
      animation-play-state: paused;
    }
  }
}

.infinite-scroll-component-box-top,
.infinite-scroll-component-box-bottom {
  .scroll-content {
    width: 100%;

    .loop-item {
      width: 100%;
    }
  }
}

// 动画 - 向左滚动
.infinite-scroll-component-box-left .scroll-content {
  flex-direction: row;
  animation: var(--speed-) move-left linear infinite;

  @keyframes move-left {
    0% {
      transform: translateX(0)
    }
    100% {
      transform: translateX(-50%)
    }
  }
}

// 动画 - 向右滚动
.infinite-scroll-component-box-right .scroll-content {
  flex-direction: row-reverse;
  animation: var(--speed-) move-right linear infinite;

  @keyframes move-right {
    0% {
      transform: translateX(-50%)
    }
    100% {
      transform: translateX(0);
    }
  }
}

// 动画 - 向上滚动
.infinite-scroll-component-box-top .scroll-content {
  flex-direction: column;
  animation: var(--speed-) move-top linear infinite;

  @keyframes move-top {
    0% {
      transform: translateY(0);
    }
    100% {
      transform: translateY(-50%);
    }
  }
}

// 动画 - 向下滚动
.infinite-scroll-component-box-bottom .scroll-content {
  flex-direction: column-reverse;
  animation: var(--speed-) move-bottom linear infinite;

  @keyframes move-bottom {
    0% {
      transform: translateY(-50%);
    }
    100% {
      transform: translateY(0);
    }
  }
}
</style>
 
 <template>
  <div
    ref="scrollBox"
    :class="`infinite-scroll-component-box-${direction}`"
    :style="{
      '--speed-': `${speed}s`,
      'mask': `linear-gradient(${degList[direction]}, #000 70%, transparent)`
    }"
  >
    <div class="scroll-content" ref="scrollContent">
      <!-- 如果是数据是数组 -->
      <template v-if="Array.isArray(content)">
        <!-- 滚动数据 -->
        <div v-for="(item, index) in content" :key="`arrayFirst${index}`" class="loop-item">
          <slot :item="item" :index="index" />
        </div>
        <!-- 滚动数据的副本 -->
        <template v-if="loop">
          <div v-for="(item, index) in content" :key="`arrayCopy${index}`" class="loop-item">
            <slot :item="item" :index="index" />
          </div>
        </template> 
      </template>
      <!-- 如果数据不是数组的时候 -->
      <template v-else>
        <slot />
        <slot v-if="loop" />
      </template>
    </div>
  </div>
 </template>
 
 <script setup>
import { ref, onMounted, nextTick, watch } from 'vue'

const props = defineProps({
  // 滚动的方向
  direction: {
    type: String,
    default: 'left',
    validate: (value) => ['left', 'right', 'top', 'bottom'].findIndex(value) !== -1
  },
  // 数据
  content: {
    type: [String, Array],
    default: ''
  },
  // 是否暂时阴影
  mask: {
    type: Boolean,
    default: false
  },
  // 滚动速度
  speedRate: {
    type: Number,
    default: 50
  }
})

onMounted(() => {
  init()
})

// 阴影的方向
const degList = {
  left: '90deg',
  top: '180deg',
  right: '270deg',
  bottom: '0deg',
}

// 滚动速度
const speed = ref(0)
// 是否需要无限滚动
const loop = ref(false)
// 滚动盒子
const scrollBox = ref(null)

watch(() => props.content, () => {
  loop.value = true
  init()
}, { deep: true })

// 初始化速度，以及是否需要无限滚动
const init = async () => {
  await nextTick()
  if (['left', 'right'].includes(props.direction)) {
    // 可是区域宽度
    const boxWidth = scrollBox.value.offsetWidth
    // 滚动内容的宽度
    const itemWidth = scrollBox.value.getElementsByClassName('scroll-content')[0].offsetWidth
    if (itemWidth > boxWidth) {
      loop.value = true
      speed.value = itemWidth / props.speedRate
    } else {
      speed.value = 0
      scrollBox.value.getElementsByClassName('scroll-content')[0].style.transform = 'translateX(0)'
      loop.value = false
    }
  } else {
    // 可是区域高度
    const boxHeight = scrollBox.value.offsetHeight
    // 滚动内容的高度
    const itemHeight = scrollBox.value.getElementsByClassName('scroll-content')[0].offsetHeight
    if (itemHeight >= boxHeight) {
      loop.value = true
      speed.value = itemHeight / props.speedRate
    } else {
      speed.value = 0
      scrollBox.value.getElementsByClassName('scroll-content')[0].style.transform = 'translateY(0)'
      loop.value = false
    }
  }
}
</script>